package xyz.xpman.prisonerfitness.activity;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CalendarView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.annotation.RequiresApi;
import androidx.arch.core.util.Function;

import org.jetbrains.annotations.NotNull;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

import xyz.xpman.prisonerfitness.R;
import xyz.xpman.prisonerfitness.activity.base.BaseActivity;
import xyz.xpman.prisonerfitness.adapter.TrainingRecordSimpleAdapter;
import xyz.xpman.prisonerfitness.entity.TrainingRecord;
import xyz.xpman.prisonerfitness.entity.TrainingThoughts;
import xyz.xpman.prisonerfitness.kit.CaptureKit;
import xyz.xpman.prisonerfitness.kit.ColorKit;
import xyz.xpman.prisonerfitness.kit.DateKit;
import xyz.xpman.prisonerfitness.kit.FileProviderKit;
import xyz.xpman.prisonerfitness.kit.FormatKit;
import xyz.xpman.prisonerfitness.kit.ShareKit;
import xyz.xpman.prisonerfitness.kit.ViewKit;
import xyz.xpman.prisonerfitness.service.TrainingRecordService;
import xyz.xpman.prisonerfitness.service.TrainingThoughtsService;
import xyz.xpman.prisonerfitness.share.FileModel;
import xyz.xpman.prisonerfitness.util.AppUtil;
import xyz.xpman.prisonerfitness.util.FileUtil;
import xyz.xpman.prisonerfitness.util.ToastUtil;

/**
 * 训练日记
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public class TrainingDiaryActivity extends BaseActivity {
    public static final String DATE_FORMAT = "yyyy年 MM月 dd日";
    @SuppressLint("NewApi")
    public static final Map<Integer, String> DAY_STRING_OF_WEEK = Map.ofEntries(
            Map.entry(1, "一"),
            Map.entry(2, "二"),
            Map.entry(3, "三"),
            Map.entry(4, "四"),
            Map.entry(5, "五"),
            Map.entry(6, "六"),
            Map.entry(7, "天"));

    private TrainingThoughts trainingThoughts;

    private TextView date;
    private TextView dayOfWeek;
    private CalendarView calendar;
    private LinearLayout calendarLayout;

    private ScrollView scrollView;
    private LinearLayout body;
    private EditText thoughts;
    private TextView thoughtsDisplay;
    private ImageView saveThoughts;

    private LinearLayout records;
    private TextView trainingTime;

    private LinearLayout noRecords;

    private LocalDate displayDate = LocalDate.now();
    private ImageButton shareBtn;

    private Supplier<Boolean> calendarTouchEvent;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_training_diary);
        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
//        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        initView();
        initEvent();

        processTrainingDiary(displayDate);

        // 获取calendarLayout的高度（显示时ScrollView需要根据这个来设置marginTop）
        // 初始化之后，就可以直接view.getHeight()或view.getWidth()得到数据
        // ViewKit.getSize(calendarLayout, (height, width) ->
        //         Log.i("CalendarLayout", "width: " + width + ", height: " + height));
        ViewKit.getSize(calendarLayout, (height, width) -> { });
    }

    private void initView() {
        date = findViewById(R.id.date);

        calendarLayout = findViewById(R.id.calendar_layout);

        calendar = findViewById(R.id.calendar);
        calendar.setMinDate(AppUtil.getFirstInstallTime());
        calendar.setMaxDate(System.currentTimeMillis());
        calendar.setDate(System.nanoTime());



        scrollView = findViewById(R.id.scroll_view);
        body = findViewById(R.id.body);

        thoughts = findViewById(R.id.thoughts);
        saveThoughts = findViewById(R.id.save_thoughts);
        thoughtsDisplay = findViewById(R.id.thoughts_display);
        dayOfWeek = findViewById(R.id.day_of_week);

        records = findViewById(R.id.have_training_record);
        noRecords = findViewById(R.id.no_training_record);
        trainingTime = findViewById(R.id.training_time);


        shareBtn = findViewById(R.id.share);
    }


    @SuppressLint({"ClickableViewAccessibility", "UseCompatLoadingForDrawables"})
    private void initEvent() {
        // 前提调节：日期日期式当日（不是当日thoughtsDisplay会隐藏起来 -> 不会出发点击事件）
        thoughtsDisplay.setOnClickListener(view -> {
            if (isToday()) {
                thoughtsToEditMode();


                // 自动获取焦点
                thoughts.requestFocus();
                // thoughts.requestFocusFromTouch();
                // getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
            }
        });


        saveThoughts.setOnClickListener(view -> {
            if (saveThoughts()) {
                thoughtsDisplay.setText(thoughts.getText());
                thoughtsToShowMode();
            } else {
                ToastUtil.showText(this, "保存失败！");
            }
        });


        // TODO: 2021/6/21 month 不知为何少一月, month从0开始？
        calendar.setOnDateChangeListener((view, year, month, dayOfMonth) -> {
            final LocalDate date = LocalDate.of(year, month + 1, dayOfMonth);

            // 日期变化
            if (!date.isEqual(displayDate)) {
                displayDate = date;
                processTrainingDiary(date);

                // 隐藏日历，并取消日历菜单按钮高亮状态
                calendarTouchEvent.get();
            }
        });


        shareBtn.setOnClickListener(view -> share());
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private void thoughtsToShowMode() {
        thoughtsDisplay.setVisibility(View.VISIBLE);
        shareBtn.setVisibility(View.VISIBLE);

        thoughts.setVisibility(View.GONE);
        saveThoughts.setVisibility(View.GONE);
    }

    private void thoughtsToEditMode() {
        thoughtsDisplay.setVisibility(View.GONE);
        shareBtn.setVisibility(View.GONE);

        thoughts.setVisibility(View.VISIBLE);
        saveThoughts.setVisibility(View.VISIBLE);
    }


    private void processScrollViewMargin(boolean hideCalendar) {
        final ViewGroup.MarginLayoutParams params =
                (ViewGroup.MarginLayoutParams) scrollView.getLayoutParams();

        if (hideCalendar) {
            params.topMargin = 0;
        } else {
            params.topMargin = calendarLayout.getHeight();
        }

        scrollView.setLayoutParams(params);
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private boolean saveThoughts() {
        Log.i("TrainingDairy", "saveThoughts");

        String text = thoughts.getText().toString();

        if (null == trainingThoughts) {
            trainingThoughts = TrainingThoughts.by(text, displayDate);
            return TrainingThoughtsService.ME.save(trainingThoughts);
        } else {
            trainingThoughts.setThoughts(text);
            return TrainingThoughtsService.ME.update(trainingThoughts);
        }
    }


    private boolean share() {
        final Bitmap img = CaptureKit.captureView(body, Color.WHITE);

        final String fmt =
                "{esd}/Pictures/{fileName}/{yyyy-MM-dd_HH-mm-ss}.png";
        final String fileName = FormatKit.parse(fmt, AppUtil.getName());
        Log.i( "share", fileName);


        boolean bool = FileUtil.saveToFile(fileName, img);

        if (!bool) {
            ToastUtil.showText(this, "生成图片失败！");
            return false;
        }



        // 分享图片
        final Uri uri = FileProviderKit.by(this, fileName);
        final FileModel temp = new FileModel(uri, "image/*", "选择分享应用");
        Log.i("share-uri", uri.toString());

        ShareKit.file(this, temp);
        return true;
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private void processTrainingDiary(@NotNull final LocalDate date) {
        int dayOfWeek = date.getDayOfWeek().getValue();
        this.dayOfWeek.setText(DAY_STRING_OF_WEEK.get(dayOfWeek));
        this.date.setText(DateKit.format(date, DATE_FORMAT));


        // trainingRecords
        List<TrainingRecord> records = TrainingRecordService.ME.findByDate(date);
        // Log.i("TrainingDiaryActivity", date + ": " + records);


        if (records.isEmpty()) {
            // 无训练记录则隐藏（显示“点击即可输入今日锻炼感想”，隐藏锻炼记录）
            this.records.setVisibility(View.GONE);
            this.noRecords.setVisibility(View.VISIBLE);
        } else {
            // 有训练记录则展示
            int usedTime = TrainingRecord.countUsedTime(records);
            this.trainingTime.setText(String.valueOf(usedTime));
            processRecords(records);

            this.noRecords.setVisibility(View.GONE);
            this.records.setVisibility(View.VISIBLE);
        }



        // thoughts
        trainingThoughts = TrainingThoughtsService.ME.findByDate(date);
        final String temp =
                null != trainingThoughts ? trainingThoughts.getThoughts() : "";
        this.thoughts.setText(temp);
        this.thoughtsDisplay.setText(temp);

        if (!isToday()) {
            thoughts.setVisibility(View.GONE);
            saveThoughts.setVisibility(View.GONE);

            if (null == trainingThoughts) {
                thoughtsDisplay.setVisibility(View.GONE);
                return;
            }
        }
        thoughtsDisplay.setVisibility(View.VISIBLE);
    }


    private void processRecords(@NotNull List<TrainingRecord> records) {
        final ListView listView = findViewById(R.id.training_records);

        final ListAdapter adapter = new TrainingRecordSimpleAdapter(
                this, R.layout.training_record_list_simple_item_temp, records);


        runOnUiThread(() -> {
            listView.setAdapter(adapter);
            setListViewHeight(listView);
        });
    }

    private void setListViewHeight(@NotNull final ListView listView) {
        final ListAdapter adapter = listView.getAdapter();
        if (adapter.isEmpty()) { return; }


        // 因为这列表项高度都一样
        final Function<ListAdapter, Integer> getHeight = (a) -> {
            View view = a.getView(0, null, listView);
            view.measure(0, 0);

            return view.getMeasuredHeight();
        };

        final int height = getHeight.apply(adapter);
        final int count = adapter.getCount();
        final int totalHeight = count * height;

        /*int totalHeight = 0;

        for(int i = 0; i < count; i++){
            View itemView = adapter.getView(i, null, listView);
            itemView.measure(0, 0);
            totalHeight += itemView.getMeasuredHeight();
        }*/

        ViewGroup.LayoutParams layoutParams = listView.getLayoutParams();
        // 总行高+每行的间距
        layoutParams.height = totalHeight + (listView.getDividerHeight() * (count - 1));
        listView.setLayoutParams(layoutParams);

        Log.i("record", String.format("count: %d, height: %d, T-Height: %d, F-Height: %d",
                count, height, totalHeight, layoutParams.height));
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    private boolean isToday() {
        return displayDate.equals(LocalDate.now());
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.training_diary_menu, menu);

        // 所有训练记录
        menu.findItem(R.id.training_records_menu).setOnMenuItemClickListener(view -> {
            toActivity(TrainingRecordsActivity.class);
            return true;
        });


        // 日历 -> 日期选择器
        final MenuItem calendarMenu = menu.findItem(R.id.date_picker_menu);
        final int whiteColor = getResources().getColor(R.color.white);
        final int orangeColor = getResources().getColor(R.color.orange);

        calendarTouchEvent = () -> {
            final int visibility = calendarLayout.getVisibility();
            final boolean hideCalendar = View.VISIBLE == visibility;

            // visibility、GONE、INVISIBLE
            if (hideCalendar) {
                calendarLayout.setVisibility(View.GONE);

                ColorKit.setColorFilter(calendarMenu, whiteColor);
            } else {
                calendarLayout.setVisibility(View.VISIBLE);

                ColorKit.setColorFilter(calendarMenu, orangeColor);
            }

            processScrollViewMargin(hideCalendar);
            return true;
        };

        calendarMenu.setOnMenuItemClickListener(view -> calendarTouchEvent.get());
        return true;
    }


    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return processMenuItemForBack(item);
    }


    // 点击两次返回退出app
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return processKeyBack(keyCode, event, () -> {
            if (thoughts.hasFocus()) {
                thoughts.clearFocus();
                thoughtsToShowMode();
                return true;
            }
            return false;
        });
    }
}